package com.ust.tk.simpletool;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.app.Activity;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Menu;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.TextView;

public class InclinationActivity extends Activity implements SensorEventListener {

	private TextView degreeText;
	private InclinationView surfaceView;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_inclination);

		degreeText = (TextView)findViewById(R.id.textView2);
		surfaceView = (InclinationView)findViewById(R.id.surfaceView2);
		initSensor();
	}

	@Override
	protected void onResume() {
		super.onResume();
		resumeSensor();
	}
	@Override
	protected void onPause() {
		super.onPause();
		releaseSensor();
	}
	@Override
	protected void onStop() {
		super.onStop();
		releaseSensor();
	}
	
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.activity_inclination, menu);
		return true;
	}


	//
	// Sensor handling
	//
	private SensorManager sensorManager = null;
	private Sensor accelerometer = null;
	private Sensor magnetometer = null;
	
	long lastUpdate;
	
	float[] mGravity;
	float[] mGeomagnetic;

    float R3x3[] = new float[9];
    float I3x3[] = new float[9];
    float orientation[] = new float[3];
    float azimut = 0f;

	private void initSensor() {
		sensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
		accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
		if ( accelerometer == null ) {
			Log.e("", "No Sensor.TYPE_ACCELEROMETER on the device...");
		}
		magnetometer = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
		if ( magnetometer == null ) {
			Log.e("", "No Sensor.TYPE_MAGNETIC_FIELD on the device...");
		}
		
		lastUpdate = System.currentTimeMillis();
	}
	private void releaseSensor() {
		if ( sensorManager != null )
			sensorManager.unregisterListener(this);
	}
	
	private void resumeSensor() {
		if ( accelerometer != null &&
			sensorManager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_NORMAL) ) 
		{
			Log.i("", "Accelerometer listener's been registered.");
		}
		if ( magnetometer != null  && 
			sensorManager.registerListener(this, magnetometer, SensorManager.SENSOR_DELAY_NORMAL) )
		{
			Log.i("", "Magnetic field listener's been registered.");
		}

	}

	@Override
	public void onSensorChanged(SensorEvent evt) {
		switch ( evt.sensor.getType() ) {
		case Sensor.TYPE_ACCELEROMETER:
			mGravity = evt.values;
			break;
		case Sensor.TYPE_MAGNETIC_FIELD:
			mGeomagnetic = evt.values;
			break;
		default:
			return;
		}

		long currTime = System.currentTimeMillis();

		if ( currTime-lastUpdate > 300 && mGravity != null && mGeomagnetic != null ) {
			lastUpdate = currTime;

			boolean success = SensorManager.getRotationMatrix(R3x3, I3x3, mGravity, mGeomagnetic);
			if (success) {
	        	SensorManager.getOrientation(R3x3, orientation);
	          	azimut = orientation[0]; // orientation contains: azimut, pitch and roll
	          	// radian to degree
	          	// 1r : (180/pi) = a : z
	          	// z = a * 180 / pi
//	          	float z = orientation[0] * 180 / 3.141592f;
//	          	if ( z < 0f ) z += 360f;
//	          	Log.i("", "onSensorChanged..." + z);

	          	//surfaceView.invalidate();
	          	//Canvas canvas = surfaceView.getHolder().lockCanvas();
	          	//surfaceView.getHolder().unlockCanvasAndPost(canvas);
	          	
	          	surfaceView.y = orientation[1];
	          	surfaceView.x = orientation[2];
	          	

	          	degreeText.setText(String.format("%.2f, %.2f", orientation[1], orientation[2]));
			
			}
		}
	}

	@Override
	public void onAccuracyChanged(Sensor arg0, int arg1) {
		
	}	
}

class InclinationView extends SurfaceView implements SurfaceHolder.Callback, Runnable {
	ExecutorService exeService = Executors.newSingleThreadExecutor();

	SurfaceHolder mHolder;
	Bitmap mBitmap;
	boolean mRunning = false;
	public float x = 0f;
	public float y = 0f;
	
    Paint mLinePaint = new Paint();
	
	public InclinationView(Context context, AttributeSet attrs) {
		super(context, attrs);

		//mBitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.ic_launcher);

		mHolder = getHolder();
		mHolder.addCallback(this);

	    mLinePaint.setAntiAlias(true);
	}
	
	public void begin() {
		mRunning = true;
	}
	
	public void end() {
		mRunning = false;
		//this.notify();
	}

	@Override
	public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
	}

	@Override
	public void surfaceCreated(SurfaceHolder holder) {
		this.begin();
		exeService.execute(this);		
	}

	@Override
	public void surfaceDestroyed(SurfaceHolder holder) {
		this.end();
		exeService.shutdown();
	}
	
	@Override
	public void run() {
		Canvas canvas = null;
		
		while ( mRunning ) {
			try {  
				canvas = mHolder.lockCanvas();  
				synchronized (mHolder) {  
					draw(canvas);           
				}  
			}
			finally {  
				if (canvas != null) {  
					mHolder.unlockCanvasAndPost(canvas);  
				}
			}
			//
			try {
				//this.wait();
				Thread.sleep(500);
			} catch (InterruptedException ie) {
				ie.printStackTrace();
			}
		}
	}

	
	public void draw(Canvas canvas) {
		//String strz = String.format("%.3f", z);
		float[] pts = new float[8];

		int h = canvas.getHeight();
		int w = canvas.getWidth();

		float cx = w/2;
		float cy = h/2;  // center

		// vertical
		pts[0] = cx;
		pts[1] = 0;
		pts[2] = cx;
		pts[3] = h;
		// horizontal
		pts[4] = 0;
		pts[5] = cy;
		pts[6] = w;
		pts[7] = cy;

		x = -x;
		float px = (float)(w * (x + Math.PI/2) / Math.PI);
		float py = (float)(h * (y + Math.PI/2) / Math.PI);

		canvas.drawColor(Color.WHITE);
	    mLinePaint.setStrokeWidth(3);

	    // vertical
	    mLinePaint.setColor(Color.RED);
		canvas.drawLines(pts, 0, 4, mLinePaint);
		canvas.drawCircle(cx, py, 20, mLinePaint);

		// horizontal
	    mLinePaint.setColor(Color.BLUE);
		canvas.drawLines(pts, 4, 4, mLinePaint);
		canvas.drawCircle(px, cy, 20, mLinePaint);
	}
}
